#include "gtkalias.h"
#include "gtkdnd.h"
-
#define ARROW_SIZE 12
#define ARROW_SPACING 0
#define SCROLL_DELAY_FACTOR 5
static void
do_detach_tab (GtkNotebook *from,
GtkNotebook *to,
- GtkNotebookPage *page_info,
+ GtkWidget *child,
gint x,
gint y)
{
- GtkWidget *child, *tab_label, *menu_label;
+ GtkWidget *tab_label, *menu_label;
gboolean tab_expand, tab_fill, reorderable, detachable;
GList *element;
guint tab_pack;
gint page_num;
- menu_label = tab_label = child = NULL;
+ menu_label = gtk_notebook_get_menu_label (from, child);
- if (page_info->menu_label)
- menu_label = g_object_ref (page_info->menu_label);
+ if (menu_label)
+ g_object_ref (menu_label);
- if (page_info->tab_label)
- tab_label = g_object_ref (page_info->tab_label);
+ tab_label = gtk_notebook_get_tab_label (from, child);
+
+ if (tab_label)
+ g_object_ref (tab_label);
- if (page_info->child)
- child = g_object_ref (page_info->child);
+ g_object_ref (child);
- /* preserve properties */
- tab_expand = page_info->expand;
- tab_fill = page_info->fill;
- tab_pack = page_info->pack;
- reorderable = page_info->reorderable;
- detachable = page_info->detachable;
+ gtk_container_child_get (GTK_CONTAINER (from),
+ child,
+ "tab-expand", &tab_expand,
+ "tab-fill", &tab_fill,
+ "tab-pack", &tab_pack,
+ "reorderable", &reorderable,
+ "detachable", &detachable,
+ NULL);
gtk_container_remove (GTK_CONTAINER (from), child);
guint time)
{
GtkNotebook *dest_notebook, *notebook;
- gint page_num;
if (data->target != gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB") &&
(data->target != gdk_atom_intern_static_string ("application/x-rootwindow-drop") ||
return;
notebook = GTK_NOTEBOOK (widget);
- page_num = g_list_index (notebook->children, notebook->cur_page);
if (data->target == gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB"))
{
gtk_selection_data_set (data,
data->target,
8,
- (void*) notebook->cur_page,
- sizeof (GtkNotebookPage));
+ (void*) ¬ebook->cur_page->child,
+ sizeof (gpointer));
}
else
{
window_creation_hook_data);
if (dest_notebook)
- do_detach_tab (notebook, dest_notebook, notebook->cur_page, 0, 0);
+ do_detach_tab (notebook, dest_notebook, notebook->cur_page->child, 0, 0);
}
}
{
GtkNotebook *notebook;
GtkWidget *source_widget;
- GtkNotebookPage *page_info;
+ GtkWidget **child;
notebook = GTK_NOTEBOOK (widget);
source_widget = gtk_drag_get_source_widget (context);
if (source_widget &&
data->target == gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB"))
{
- page_info = (void*) data->data;
+ child = (void*) data->data;
- do_detach_tab (GTK_NOTEBOOK (source_widget), notebook, page_info, x, y);
+ do_detach_tab (GTK_NOTEBOOK (source_widget), notebook, *child, x, y);
gtk_drag_finish (context, TRUE, FALSE, time);
}
-
- gtk_drag_finish (context, FALSE, FALSE, time);
+ else
+ gtk_drag_finish (context, FALSE, FALSE, time);
}
/* Private GtkContainer Methods :
* @child: a child #GtkWidget
* @detachable: whether the tab is detachable or not
*
- * Sets whether the tab can be detached from @notebook to another notebook.
+ * Sets whether the tab can be detached from @notebook to another
+ * notebook or widget.
*
* Note that 2 notebooks must share a common group identificator
- * (see gtk_notebook_set_group_id ()) to allow tabs interchange between them.
+ * (see gtk_notebook_set_group_id ()) to allow automatic tabs
+ * interchange between them.
+ *
+ * If you want a widget to interact with a notebook through DnD
+ * (i.e.: accept dragged tabs from it) it must be set as a drop
+ * destination and accept the target "GTK_NOTEBOOK_TAB". The notebook
+ * will fill the selection with a GtkWidget** pointing to the child
+ * widget that corresponds to the dropped tab.
+ *
+ * <informalexample><programlisting>
+ * static void
+ * on_drop_zone_drag_data_received (GtkWidget *widget,
+ * GdkDragContext *context,
+ * gint x,
+ * gint y,
+ * GtkSelectionData *selection_data,
+ * guint info,
+ * guint time,
+ * gpointer user_data)
+ * {
+ * GtkWidget *notebook;
+ * GtkWidget **child;
+ *
+ * notebook = gtk_drag_get_source_widget (context);
+ * child = (void*) selection_data->data;
+ *
+ * process_widget (*child);
+ * gtk_container_remove (GTK_CONTAINER (notebook), *child);
+ * }
+ * </programlisting></informalexample>
+ *
+ * If you want a notebook to accept drags from other widgets,
+ * you will have to set your own DnD code to do it.
*
* Since: 2.10
**/
+/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
/*
* GTK - The GIMP Toolkit
* Copyright (C) 2006 Carlos Garnacho Parro <carlosg@gnome.org>
NULL
};
+static const GtkTargetEntry button_targets[] = {
+ { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, 0 },
+};
+
static GtkNotebook*
window_creation_function (GtkNotebook *source_notebook,
GtkWidget *child,
g_print ("page %d reordered\n", page_num);
}
+static void
+on_notebook_drag_begin (GtkWidget *widget,
+ GdkDragContext *context,
+ gpointer data)
+{
+ GdkPixbuf *pixbuf;
+ guint page_num;
+
+ page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (widget));
+
+ pixbuf = gtk_widget_render_icon (widget,
+ (page_num % 2) ? GTK_STOCK_HELP : GTK_STOCK_STOP,
+ GTK_ICON_SIZE_DND, NULL);
+
+ gtk_drag_set_icon_pixbuf (context, pixbuf, 0, 0);
+ g_object_unref (pixbuf);
+}
+
+static void
+on_button_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint time,
+ gpointer user_data)
+{
+ GtkWidget *source, *tab_label;
+ GtkWidget **child;
+
+ source = gtk_drag_get_source_widget (context);
+ child = (void*) data->data;
+
+ tab_label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (source), *child);
+ g_print ("Removing tab: %s\n", gtk_label_get_text (GTK_LABEL (tab_label)));
+
+ gtk_container_remove (GTK_CONTAINER (source), *child);
+}
+
static GtkWidget*
create_notebook (gchar **labels,
gint group_id,
g_signal_connect (GTK_NOTEBOOK (notebook), "page-reordered",
G_CALLBACK (on_page_reordered), NULL);
-
+ g_signal_connect_after (G_OBJECT (notebook), "drag-begin",
+ G_CALLBACK (on_notebook_drag_begin), NULL);
return notebook;
}
+static GtkWidget*
+create_trash_button (void)
+{
+ GtkWidget *button;
+
+ button = gtk_button_new_from_stock (GTK_STOCK_DELETE);
+
+ gtk_drag_dest_set (button,
+ GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+ button_targets,
+ G_N_ELEMENTS (button_targets),
+ GDK_ACTION_MOVE);
+
+ g_signal_connect_after (G_OBJECT (button), "drag-data-received",
+ G_CALLBACK (on_button_drag_data_received), NULL);
+ return button;
+}
+
gint
main (gint argc, gchar *argv[])
{
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- table = gtk_table_new (2, 2, TRUE);
+ table = gtk_table_new (3, 2, FALSE);
gtk_notebook_set_window_creation_hook (window_creation_function, NULL);
create_notebook (tabs4, GROUP_A, PACK_ALTERNATE, GTK_POS_RIGHT),
1, 2, 1, 2);
+ gtk_table_attach (GTK_TABLE (table),
+ create_trash_button (), 1, 2, 2, 3,
+ GTK_EXPAND | GTK_FILL, GTK_SHRINK, 0, 0);
+
gtk_container_add (GTK_CONTAINER (window), table);
gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
gtk_widget_show_all (window);